package com.guojiang.guoaicodemother.service.impl;

import cn.hutool.core.util.StrUtil;
import com.guojiang.guoaicodemother.constant.UserConstant;
import com.guojiang.guoaicodemother.exception.ErrorCode;
import com.guojiang.guoaicodemother.exception.ThrowUtils;
import com.guojiang.guoaicodemother.model.dto.chatHistoryDto.ChatHistoryQueryRequest;
import com.guojiang.guoaicodemother.model.entity.App;
import com.guojiang.guoaicodemother.model.entity.User;
import com.guojiang.guoaicodemother.model.enums.ChatHistoryMessageTypeEnum;
import com.guojiang.guoaicodemother.service.AppService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.guojiang.guoaicodemother.model.entity.ChatHistory;
import com.guojiang.guoaicodemother.mapper.ChatHistoryMapper;
import com.guojiang.guoaicodemother.service.ChatHistoryService;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

import static com.guojiang.guoaicodemother.constant.ChatHistoryConstant.LOAD_CHAT_HISTORY_MAX_COUNT;

/**
 * 对话历史 服务层实现。
 *
 * @author <a href="https://gitee.com/jam-altman">程序员果酱</a>
 */
@Service
@Slf4j
public class ChatHistoryServiceImpl extends ServiceImpl<ChatHistoryMapper, ChatHistory> implements ChatHistoryService {


    @Resource
    @Lazy
    private AppService appService;

    /**
     * 添加对话历史记录
     *
     * @param appId
     * @param message
     * @param messageType
     * @param userId
     * @return
     */
    @Override
    public boolean addChatMessage(Long appId, String message, String messageType, Long userId) {
        ThrowUtils.throwIf(appId == null || appId <= 0, ErrorCode.PARAMS_ERROR, "请求参数错误");
        ThrowUtils.throwIf(StrUtil.isBlank(message), ErrorCode.PARAMS_ERROR, "请求参数错误");
        ThrowUtils.throwIf(StrUtil.isBlank(messageType), ErrorCode.PARAMS_ERROR, "请求参数错误");
        ThrowUtils.throwIf(userId == null || userId <= 0, ErrorCode.PARAMS_ERROR, "请求参数错误");
        // 验证消息类型是否有效
        ChatHistoryMessageTypeEnum messageTypeEnum = ChatHistoryMessageTypeEnum.getEnumByValue(messageType);
        ThrowUtils.throwIf(messageTypeEnum == null, ErrorCode.PARAMS_ERROR, "不支持的消息类型: " + messageType);
        ChatHistory chatHistory = ChatHistory.builder()
                .appId(appId)
                .message(message)
                .messageType(messageType)
                .userId(userId)
                .build();
        boolean saveResult = save(chatHistory);
        ThrowUtils.throwIf(!saveResult, ErrorCode.SYSTEM_ERROR, "添加对话历史记录失败");
        return true;
    }

    /**
     * 根据应用 ID 删除对话历史记录
     *
     * @param appId
     * @return
     */
    @Override
    public boolean deleteChatMessageByAppId(Long appId) {
        ThrowUtils.throwIf(appId == null || appId <= 0, ErrorCode.PARAMS_ERROR, "请求参数错误");
        QueryWrapper wrapper = QueryWrapper.create().eq("appId", appId);
        boolean removeResult = remove(wrapper);
        ThrowUtils.throwIf(!removeResult, ErrorCode.SYSTEM_ERROR, "删除对话历史记录失败，请稍候重试");
        return true;
    }

    /**
     * 游标查询对话历史记录
     *
     * @param appId
     * @param pageSize
     * @param lastCreateTime
     * @param loginUser
     * @return
     */
    @Override
    public Page<ChatHistory> listAppChatHistoryByPage(Long appId, int pageSize, LocalDateTime lastCreateTime, User loginUser) {
        ThrowUtils.throwIf(appId == null || appId <= 0, ErrorCode.PARAMS_ERROR, "请求参数错误");
        ThrowUtils.throwIf(pageSize <= 0 || pageSize > 50, ErrorCode.PARAMS_ERROR, "请求参数错误");
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
        // 验证权限：只有应用创建者和管理员可以查看
        App app = appService.getById(appId);
        ThrowUtils.throwIf(app == null, ErrorCode.NOT_FOUND_ERROR, "应用不存在");
        boolean isAdmin = UserConstant.ADMIN_ROLE.equals(loginUser.getUserRole());
        boolean isCreator = app.getUserId().equals(loginUser.getId());
        ThrowUtils.throwIf(!isAdmin && !isCreator, ErrorCode.NO_AUTH_ERROR, "无权限");
        // 构建查询条件
        ChatHistoryQueryRequest queryRequest = new ChatHistoryQueryRequest();
        queryRequest.setAppId(appId);
        queryRequest.setLastCreateTime(lastCreateTime);
        QueryWrapper queryWrapper = getQueryWrapper(queryRequest);
        // 查询数据
        return page(Page.of(1, pageSize), queryWrapper);
    }


    /**
     * 初始化 AI 服务实例时，将数据库中的对话历史记录加载到对话记忆中
     *
     * @param appId
     * @param chatMemory
     * @return
     */
    @Override
    public int loadChatHistoryToMemory(long appId, MessageWindowChatMemory chatMemory) {
        try {
            QueryWrapper queryWrapper = QueryWrapper.create()
                    .eq(ChatHistory::getAppId, appId)
                    .orderBy(ChatHistory::getCreateTime, false)
                    // AI 服务实例会自动将用户当前输入消息作为输入，所以这里 offset 为 1，避免重复加载用户消息 
                    .limit(1, LOAD_CHAT_HISTORY_MAX_COUNT);
            List<ChatHistory> historyList = this.list(queryWrapper);
            if (historyList.isEmpty()) {
                return 0;
            }
            Collections.reverse(historyList);
            // 加载成功的消息数量
            int loadedCount = 0;
            // 清理对话记忆，防止重复加载并确保 AI 得到的是最新的消息
            chatMemory.clear();
            for (ChatHistory chatHistory : historyList) {
                if (ChatHistoryMessageTypeEnum.USER.getValue().equals(chatHistory.getMessageType())) {
                    chatMemory.add(new UserMessage(chatHistory.getMessage()));
                    loadedCount++;
                } else if (ChatHistoryMessageTypeEnum.AI.getValue().equals(chatHistory.getMessageType())) {
                    chatMemory.add(new AiMessage(chatHistory.getMessage()));
                    loadedCount++;
                } else {
                    log.debug("发现一条未知类型的对话历史记录，忽略加载，它的 ID 是：{}", chatHistory.getId());
                }
            }
            log.debug("成功为应用 ID 为 {} 的 AI 服务实例加载 {} 条对话历史记录", appId, loadedCount);
            return loadedCount;
        } catch (Exception e) {
            // 加载失败，不影响 AI 服务实例的初始化，只是会少一些上下文信息
            // 不能影响用户直观的使用体验，所以这里只是记录日志
            log.error("加载对话历史失败，AppId：{}，错误消息：{}", appId, e.getMessage(), e);
            return 0;
        }
    }

    /**
     * 构造查询条件
     *
     * @param chatHistoryQueryRequest
     * @return
     */
    @Override
    public QueryWrapper getQueryWrapper(ChatHistoryQueryRequest chatHistoryQueryRequest) {
        QueryWrapper queryWrapper = QueryWrapper.create();
        if (chatHistoryQueryRequest == null) {
            return queryWrapper;
        }
        Long id = chatHistoryQueryRequest.getId();
        String message = chatHistoryQueryRequest.getMessage();
        String messageType = chatHistoryQueryRequest.getMessageType();
        Long appId = chatHistoryQueryRequest.getAppId();
        Long userId = chatHistoryQueryRequest.getUserId();
        LocalDateTime lastCreateTime = chatHistoryQueryRequest.getLastCreateTime();
        String sortField = chatHistoryQueryRequest.getSortField();
        String sortOrder = chatHistoryQueryRequest.getSortOrder();
        // 拼接查询条件
        queryWrapper.eq("id", id)
                .like("message", message)
                .eq("messageType", messageType)
                .eq("appId", appId)
                .eq("userId", userId);
        // 游标查询逻辑 - 只使用 createTime 作为游标
        if (lastCreateTime != null) {
            queryWrapper.le("createTime", lastCreateTime);
        }
        // 排序
        if (StrUtil.isNotBlank(sortField)) {
            queryWrapper.orderBy(sortField, "ascend".equals(sortOrder));
        } else {
            // 默认按创建时间降序排列
            queryWrapper.orderBy("createTime", false);
        }
        return queryWrapper;
    }

}
